package com.ywu.third.exec.standard.exec.impl;

import com.ywu.boot.exception.YwuRuntimeException;
import com.ywu.file.sys.sdk.enter.YwuFileSysExec;
import com.ywu.third.exec.standard.config.YwuThirdExecConfig;
import com.ywu.third.exec.standard.entity.YwuThirdExecEntity;
import com.ywu.third.exec.standard.exec.YwuThirdExecEngine;
import com.ywu.third.exec.standard.exec.param.ParamParseCoreService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @ClassName YwuJavaClassExecEngine
 * @Description TODO
 * @Author GroundDemo
 * @Date 2024/10/14 11:16
 * @Version 1.0
 **/
@Component
@Slf4j
public class YwuJavaClassExecEngine implements YwuThirdExecEngine {

    private static final String LOAD_CLASS_NAME = "YwuThirdExecClass";

    private static final String EXEC_MAIN_METHOD_NAME = "handlerCoreService";

    @Autowired
    private YwuFileSysExec ywuFileSysExec;

    @Autowired
    private ParamParseCoreService paramParseCoreService;

    @Autowired
    private YwuThirdExecConfig config;

    private static final String JAVA_CLASS_ENGINE_TYPE = "class";

    /**
    * @Author GroundDemo
    * @Description 执行类型
    * @Date 9:02 2024/10/16
    * @Param []
    * @return java.lang.String
    **/
    @Override
    public String execType() {
        return JAVA_CLASS_ENGINE_TYPE;
    }

    /**
    * @Author GroundDemo
    * @Description 执行核心逻辑
    * @Date 9:02 2024/10/16
    * @Param [entity]
    * @return java.lang.Object
    **/
    @Override
    public Object exec(YwuThirdExecEntity entity) {
        // 解析参数
        Map<String, Object> paramMap = paramParseCoreService.parseThirdExecParam(entity);
        // 下载文件
        String filePath = downloadThirdFile(entity, ywuFileSysExec);
        // 备份file至唯一的文件夹中
        String newFileDirs;
        try {
            newFileDirs = copyFile(filePath);
        } catch (Exception e) {
            return null;
        }
        // 使用URLClassLoader加载Class文件
        File classFile = new File(newFileDirs);
        URL classUrl;
        URLClassLoader classLoader = null;
        Object result = null;
        try {
            classUrl = classFile.toURI().toURL();
            URL[] classUrls = new URL[]{classUrl};
            // 获取URL类加载器
            classLoader = new URLClassLoader(classUrls);
            // 加载类并获取其Class对象
            Class<?> clazz = classLoader.loadClass(LOAD_CLASS_NAME);
            // 获取执行的方法
            Method execMethod = getMethod(clazz, EXEC_MAIN_METHOD_NAME);
            if (Objects.isNull(execMethod)) {
                log.error("no execMethod error {}", EXEC_MAIN_METHOD_NAME);
                return null;
            }
            // 获取方法中的所有参数名称
            List<Object> params = getExecParams(execMethod, paramMap);
            // 创建对象
            Object tempClass = clazz.newInstance();
            result = execMethod.invoke(tempClass, params.toArray());
        } catch (MalformedURLException | ClassNotFoundException |
                InstantiationException | IllegalAccessException | InvocationTargetException e) {
            log.error("class exec error {}", e.getMessage());
        } finally {
            // 删除下载的文件
            clearDelete(newFileDirs, classLoader);
        }
        return result;
    }

    /**
    * @Author GroundDemo
    * @Description 刪除资源
    * @Date 11:57 2024/10/16
    * @Param [newFileDirs, classLoader]
    * @return void
    **/
    private void clearDelete(String newFileDirs, URLClassLoader classLoader) {
        // 删除资源
        File file = new File(newFileDirs);
        try {
            FileUtils.deleteDirectory(file);
        } catch (IOException e) {
            log.error("class dir delete error {}", e.getMessage());
        }
        if (Objects.nonNull(classLoader)) {
            try {
                classLoader.close();
            } catch (IOException e) {
                log.error("class loader close error {}", e.getMessage());
            }
        }
    }

    /**
    * @Author GroundDemo
    * @Description 将下载下的文件备份
    * @Date 10:43 2024/10/16
    * @Param [filePath]
    * @return java.lang.String
    **/
    private String copyFile(String filePath) {
        File sourceFile = new File(filePath);
        String[] split = filePath.split("/");
        String fileId = split[split.length - 1];
        String newFileDir = config.getTempFilePath() + File.separator + fileId;
        File fileDir = new File(newFileDir);
        if (!fileDir.exists() && !fileDir.mkdirs()) {
            log.error("file dir make error {}", newFileDir);
            sourceFile.delete();
            throw new YwuRuntimeException("file dir make error");
        }
        String newFilePath = newFileDir + File.separator + LOAD_CLASS_NAME + ".class";
        try {
            FileUtils.copyFile(sourceFile, new File(newFilePath));
        } catch (IOException e) {
            log.error("copy file error");
            throw new YwuRuntimeException("copy file error");
        } finally {
            sourceFile.delete();
        }
        return newFileDir;
    }

}
